# flask_app/app.py
from flask import Flask, render_template, request, redirect, url_for, flash
import requests
import json

API_BASE = "http://127.0.0.1:8000"  # FastAPI backend - adjust if different

app = Flask(__name__, template_folder="templates", static_folder="static")
app.secret_key = "replace-with-a-secure-secret-in-prod"


# -------------------------------------------------------
# Helper functions: API wrappers with graceful error handling
# -------------------------------------------------------

def _parse_api_error(resp):
    """Return a readable error message from API or HTTP error."""
    try:
        data = resp.json()
        if isinstance(data, dict) and "detail" in data:
            detail = data["detail"]
            if isinstance(detail, list):
                # pydantic validation errors
                return "; ".join(f"{d.get('msg')}" for d in detail)
            return str(detail)
        return str(data)
    except Exception:
        return resp.text


def api_get(path, params=None):
    try:
        r = requests.get(f"{API_BASE}{path}", params=params, timeout=8)
        r.raise_for_status()
        return r.json(), None
    except requests.HTTPError as e:
        return None, _parse_api_error(e.response)
    except Exception as e:
        return None, str(e)


def api_post(path, payload):
    try:
        r = requests.post(f"{API_BASE}{path}", json=payload, timeout=8)
        if r.status_code in (200, 201):
            try:
                return r.json(), None
            except ValueError:
                return {}, None
        else:
            return None, _parse_api_error(r)
    except requests.RequestException as e:
        return None, str(e)


def api_put(path, payload):
    try:
        r = requests.put(f"{API_BASE}{path}", json=payload, timeout=8)
        if r.ok:
            try:
                return r.json(), None
            except ValueError:
                return {}, None
        else:
            return None, _parse_api_error(r)
    except requests.RequestException as e:
        return None, str(e)


def api_delete(path):
    try:
        r = requests.delete(f"{API_BASE}{path}", timeout=8)
        if r.status_code in (200, 204):
            return True, None
        else:
            return False, _parse_api_error(r)
    except requests.RequestException as e:
        return False, str(e)


# -------------------------------------------------------
# Routes
# -------------------------------------------------------

@app.route("/")
def index():
    return redirect(url_for("patients"))


# -----------------------
# Patients
# -----------------------
@app.route("/patients")
def patients():
    name = request.args.get("name")
    params = {"name": name} if name else None
    data, err = api_get("/patients", params=params)
    if err:
        flash(f"⚠️ Failed to load patients: {err}", "danger")
        data = []
    return render_template("patients.html", patients=data or [], name=name or "")


def _build_emergency_contact_from_form():
    ec_name = request.form.get("ec_name")
    ec_phone = request.form.get("ec_phone")
    ec_relation = request.form.get("ec_relation")
    if ec_name or ec_phone or ec_relation:
        return {"name": ec_name or "", "phone": ec_phone or "", "relation": ec_relation or ""}
    ec_raw = request.form.get("emergency_contact")
    if not ec_raw:
        return None
    try:
        parsed = json.loads(ec_raw)
        if isinstance(parsed, dict):
            return parsed
    except Exception:
        pass
    return {"phone": ec_raw}


@app.route("/patients/create", methods=["POST"])
def create_patient():
    ec = _build_emergency_contact_from_form()
    payload = {
        "first_name": request.form.get("first_name"),
        "last_name": request.form.get("last_name"),
        "date_of_birth": request.form.get("date_of_birth"),
        "gender": request.form.get("gender"),
        "email": request.form.get("email"),
        "phone": request.form.get("phone"),
        "address": request.form.get("address"),
        "emergency_contact": ec,
        "is_active": True,
    }
    _, err = api_post("/patients", payload)
    if err:
        flash(f"❌ Error creating patient: {err}", "danger")
    else:
        flash("✅ Patient created successfully.", "success")
    return redirect(url_for("patients"))


@app.route("/patients/delete/<int:patient_id>", methods=["POST"])
def delete_patient(patient_id):
    ok, err = api_delete(f"/patients/{patient_id}")
    if not ok:
        flash(f"❌ Error deleting patient: {err}", "danger")
    else:
        flash("🗑️ Patient deleted successfully.", "info")
    return redirect(url_for("patients"))


@app.route("/patients/edit/<int:patient_id>", methods=["GET", "POST"])
def edit_patient(patient_id):
    if request.method == "POST":
        payload = {k: v for k, v in request.form.items() if v != "" and k not in ("ec_name", "ec_phone", "ec_relation")}
        ec = _build_emergency_contact_from_form()
        if ec:
            payload["emergency_contact"] = ec
        payload.setdefault("is_active", True)

        _, err = api_put(f"/patients/{patient_id}", payload)
        if err:
            flash(f"❌ Error updating patient: {err}", "danger")
            return redirect(url_for("edit_patient", patient_id=patient_id))
        flash("✅ Patient updated successfully.", "success")
        return redirect(url_for("patients"))
    data, err = api_get(f"/patients/{patient_id}")
    if err:
        flash(f"⚠️ Failed to load patient details: {err}", "danger")
        return redirect(url_for("patients"))
    return render_template("patients.html", edit_patient=data)


# -----------------------
# Appointments
# -----------------------
@app.route("/appointments")
def appointments():
    params = {k: v for k, v in request.args.items() if v}
    data, err = api_get("/appointments", params=params or None)
    if err:
        flash(f"⚠️ Failed to load appointments: {err}", "danger")
        data = []
    return render_template("appointments.html", appointments=data or [])


@app.route("/appointments/create", methods=["POST"])
def create_appointment():
    payload = {
        "patient_id": int(request.form.get("patient_id")),
        "staff_id": int(request.form.get("staff_id")),
        "department_id": int(request.form.get("department_id")) if request.form.get("department_id") else None,
        "appointment_datetime": request.form.get("appointment_datetime"),
        "duration_minutes": int(request.form.get("duration_minutes") or 30),
        "reason": request.form.get("reason"),
        "status": request.form.get("status") or "scheduled",
    }
    _, err = api_post("/appointments", payload)
    if err:
        flash(f"❌ Could not create appointment: {err}", "danger")
    else:
        flash("✅ Appointment created successfully.", "success")
    return redirect(url_for("appointments"))


@app.route("/appointments/delete/<int:appointment_id>", methods=["POST"])
def delete_appointment(appointment_id):
    ok, err = api_delete(f"/appointments/{appointment_id}")
    if not ok:
        flash(f"❌ Error deleting appointment: {err}", "danger")
    else:
        flash("🗑️ Appointment deleted successfully.", "info")
    return redirect(url_for("appointments"))


# -----------------------
# Medical Records
# -----------------------
@app.route("/medical-records")
def medical_records():
    patient_id = request.args.get("patient_id")
    if patient_id:
        data, err = api_get(f"/medical-records/patient/{patient_id}")
    else:
        data, err = [], None
    if err:
        flash(f"⚠️ Failed to load records: {err}", "danger")
        data = []
    return render_template("medical_records.html", records=data or [], patient_id=patient_id)


@app.route("/medical-records/create", methods=["POST"])
def create_medical_record():
    payload = {
        "appointment_id": int(request.form.get("appointment_id")),
        "patient_id": int(request.form.get("patient_id")),
        "diagnosis": request.form.get("diagnosis"),
        "symptoms": request.form.get("symptoms"),
        "observations": request.form.get("observations"),
    }
    _, err = api_post("/medical-records", payload)
    if err:
        flash(f"❌ Could not create medical record: {err}", "danger")
    else:
        flash("✅ Medical record created successfully.", "success")
    return redirect(url_for("medical_records"))


@app.route("/medical-records/delete/<int:record_id>", methods=["POST"])
def delete_medical_record(record_id):
    ok, err = api_delete(f"/medical-records/{record_id}")
    if not ok:
        flash(f"❌ Error deleting record: {err}", "danger")
    else:
        flash("🗑️ Medical record deleted successfully.", "info")
    return redirect(url_for("medical_records"))


# -----------------------
# Prescriptions
# -----------------------
@app.route("/prescriptions")
def prescriptions():
    data, err = api_get("/prescriptions")
    if err:
        flash(f"⚠️ Failed to load prescriptions: {err}", "danger")
        data = []
    return render_template("prescriptions.html", prescriptions=data or [])


@app.route("/prescriptions/create", methods=["POST"])
def create_prescription():
    items = []
    index = 0
    while True:
        key = f"items-{index}-medication_id"
        if key not in request.form:
            break
        items.append({
            "medication_id": int(request.form.get(f"items-{index}-medication_id")),
            "dosage": request.form.get(f"items-{index}-dosage"),
            "frequency": request.form.get(f"items-{index}-frequency"),
            "duration_days": int(request.form.get(f"items-{index}-duration_days") or 0),
        })
        index += 1

    payload = {
        "appointment_id": int(request.form.get("appointment_id")),
        "prescribed_by": int(request.form.get("prescribed_by")),
        "notes": request.form.get("notes"),
        "items": items,
    }
    _, err = api_post("/prescriptions", payload)
    if err:
        flash(f"❌ Could not create prescription: {err}", "danger")
    else:
        flash("✅ Prescription created successfully.", "success")
    return redirect(url_for("prescriptions"))


@app.route("/prescriptions/<int:prescription_id>")
def view_prescription(prescription_id):
    data, err = api_get(f"/prescriptions/{prescription_id}")
    if err:
        flash(f"⚠️ Failed to load prescription: {err}", "danger")
        return redirect(url_for("prescriptions"))
    return render_template("prescriptions.html", prescriptions=[data], single=True)


# -----------------------
# Reports
# -----------------------
@app.route("/reports", methods=["GET", "POST"])
def reports():
    """
    Display hospital reports and allow filtering available staff by date.
    """
    # Handle both GET and POST for flexibility (form submissions)
    date = request.values.get("date")  # handles both GET and POST

    # Load core reports
    appointments, e1 = api_get("/reports/appointments/details")
    revenue, e2 = api_get("/reports/revenue/department")
    outstanding, e3 = api_get("/reports/patients/outstanding")

    # Available staff
    available, e4 = None, None
    if date:
        available, e4 = api_get("/reports/appointments/available", params={"date": date})

    # Combine any errors for flash display
    errors = [e for e in (e1, e2, e3, e4) if e]
    if errors:
        flash("⚠️ Some reports failed: " + "; ".join(errors), "warning")

    return render_template(
        "reports.html",
        appointments=appointments or [],
        revenue=revenue or [],
        outstanding=outstanding or [],
        available=available or [],
        date=date or ""
    )



if __name__ == "__main__":
    app.run(port=5000, debug=True)
